#include "chatcommand_leavesimplegame.h"
#include "websocket.h"
#include "datastring.h"
#include "parameters.h"
#include "stringbuilder.h"
#include "message.h"
#include "Debug.h"
#include <inttypes.h>
#include "simplechatgame.h"

// leavesimplegame(messageid,gameid,offset,newgamedata)
// Leaves a simple game. Returns a simplegameleave message or an error. Offset is where to save newgamedata within gamedata. Use -1 to replace.
bool chatcommand_leavesimplegame::processmessage(char first_letter,message *received_message,chatclient *client)
{
	if ((first_letter != 'l') 
		|| (received_message->actual_message.substr(0,16)!="leavesimplegame(")) {
		return false;
	}	
	
	Debug debug(__FILE__,__func__,__LINE__);
	message *new_message;
	datastring method_parameters;
	parameters parameters_parsed;
	bool parameter_success = true;
	int64_t messageid;
	datastring gameid;
	int64_t offset;
	datastring newgamedata;
	simplechatgame *game;
	datastring error_message;
	biglist_item<simplechatgame *> *gamesearch;
	biglist_item<simplechatgameuser *> *user;
	datablock *username;
	
	debug = __LINE__;
	method_parameters = received_message->actual_message.substr(16,received_message->actual_message.length-17);
	method_parameters.null_terminate(); // Used to comply with snprintf.
	parameters_parsed.long_parameter(method_parameters,parameter_success);
	parameters_parsed.string_parameter(method_parameters,parameter_success);
	parameters_parsed.long_parameter(method_parameters,parameter_success);
	parameters_parsed.string_parameter(method_parameters,parameter_success);
		
	debug = __LINE__;
	if (parameter_success) {
		// Give the parameters nice names.
		debug = __LINE__;
		messageid = parameters_parsed.long_parameters[0];
		gameid = parameters_parsed.string_parameters[1];
		offset = parameters_parsed.long_parameters[2];		
		newgamedata = parameters_parsed.string_parameters[3];
	
		debug = __LINE__;
		// Look to see if this gameid is already used.		
		gamesearch = the_websocket->find_simple_game(gameid);
		if (gamesearch == nullptr) {
			error_message = "That gameid was not found.";
			error(client,error_message,messageid);
			return true;
		}
		debug = __LINE__;
		game = gamesearch->item;
		debug = __LINE__;
		// Look for this user in this game.
		user = game->getuser(client);
		if (user == nullptr) {
			error_message = "You're not in that game.";
			error(client,error_message,messageid);
			return true;
		}
		debug = __LINE__;
		username = user->item->username == nullptr ? nullptr : user->item->username->clone();
		debug = __LINE__; 
		// Change gamedata.
		if (offset < 0) {
			if (game->gamedata == nullptr) {
				game->gamedata = new datablock(newgamedata);				
			} else {
				*(game->gamedata) = newgamedata;
			}
		} else {
			if (newgamedata.length > 0) {
				if (game->gamedata == nullptr) {
				} else {
					game->gamedata->alter(newgamedata,offset);
				}
			}
		}
		debug = __LINE__;
		// Remove this user from this game.		
		idisposable::dereference((idisposable**)&(user->item));
		user->used = false;
		debug = __LINE__;
		// Send a message to all the users that this user left the game.
		if (username == nullptr) {
		  game->send_user_list_to_clients();
		  new_message = simplegameleave(messageid,gameid,datastring::anemptystring(),game->gamedata == nullptr ? datastring::anemptystring() : *(game->gamedata));
		  // Send a message to the client that is leaving the game.
		  client->push_message(&new_message);
		} else {
		  new_message = simplegameleave(messageid,gameid,*username,game->gamedata == nullptr ? datastring::anemptystring() : *(game->gamedata));
		  idisposable::dereference((idisposable**)&username);
		  game->send_message_to_clients(new_message,nullptr);		
		  if (game->usercount(true) == 0) {
			// This game has no connected users. Delete the game.
			gamesearch->used = false;
			idisposable::dereference((idisposable**)&game);
		  }
		  // Send a message to the client that is leaving the game.
		  client->push_message(&new_message);
		}		
	} else {
		debug = __LINE__;
		parameters_not_correct(client,received_message);
	}
	debug = __LINE__;
	return true;
}
